package com.llh.uua.service

import com.llh.uua.model.SysUser
import com.llh.uua.model.SysUsers
import com.llh.uua.model.dto.AccountDto
import com.llh.uua.model.dto.AuthToken
import com.llh.uua.util.createAccessToken
import com.llh.uua.util.createRefreshToken
import org.ktorm.database.Database
import org.ktorm.dsl.and
import org.ktorm.dsl.eq
import org.ktorm.entity.add
import org.ktorm.entity.find
import org.ktorm.entity.first
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.security.core.userdetails.UserDetailsService
import org.springframework.security.core.userdetails.UsernameNotFoundException
import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.stereotype.Service
import org.springframework.security.access.AccessDeniedException

/**
 *
 *
 * Created At 2021/3/17 21:48
 * @author llh
 */
@Service
class AccountService(private val database: Database) :
    BaseService<SysUser, SysUsers>(database, SysUsers),
    UserDetailsService {

    @Autowired
    private lateinit var roleService: RoleService

    @Autowired
    private lateinit var passwordEncoder: PasswordEncoder

    override fun loadUserByUsername(username: String): UserDetails {
        val user = sequence().find { it.username eq username }

        return if (user != null) {
            val roleList = roleService.findByUserId(user.id)
            AccountDto(user).addAuthoritiesForRole(roleList)
        } else {
            throw UsernameNotFoundException("未找到用户名 $username")
        }
    }

    fun login(username: String, password: String): AuthToken {
        return loadUserByUsername(username)
            .takeIf { passwordEncoder.matches(password, it.password) }
            ?.let {
                AuthToken(createAccessToken(it), createRefreshToken(it))
            } ?: throw AccessDeniedException("用户名或密码错误")

    }


    /**
     * 注册一个账户
     */
    fun addAccount(username: String, password: String) {
        val sysUser = SysUser {
            this.username = username
            this.password = passwordEncoder.encode(password)
            enabled = true
        }
        sequence().add(sysUser)
    }
}